#include "testmap.h"

// 哈希函数（djb2算法优化版）
static unsigned long hash(const char *str)
{
    unsigned long hash = 5381;
    unsigned int c;
    while ((c = *str++))
    {
        hash = ((hash << 5) + hash) ^ c; // 使用异或替代加法
    }
    return hash;
}

// 创建节点并初始化
static Node *node_create(const char *key, unsigned int value)
{
    Node *node = malloc(sizeof(Node));
    if (!node)
        return NULL;

    node->key = strdup(key);
    if (!node->key)
    {
        free(node);
        return NULL;
    }

    node->value = value;
    node->next = NULL;
    return node;
}

// 初始化哈希表
HashMap *hashmap_create()
{
    HashMap *map = malloc(sizeof(HashMap));
    if (!map)
        return NULL;

    map->capacity = INITIAL_CAPACITY;
    map->size = 0;
    map->buckets = calloc(map->capacity, sizeof(Node *));
    if (!map->buckets)
    {
        free(map);
        return NULL;
    }
    return map;
}

// 安全扩容实现
static void hashmap_resize(HashMap *map)
{
    unsigned int old_capacity = map->capacity;
    Node **old_buckets = map->buckets;

    // 创建新桶数组
    unsigned int new_capacity = old_capacity * GROWTH_FACTOR;
    Node **new_buckets = calloc(new_capacity, sizeof(Node *));
    if (!new_buckets)
        return;

    // 转移节点到新桶
    for (int i = 0; i < old_capacity; i++)
    {
        Node *current = old_buckets[i];
        while (current)
        {
            Node *next = current->next;
            unsigned long new_index = hash(current->key) % new_capacity;

            // 插入到新桶的链表头部
            current->next = new_buckets[new_index];
            new_buckets[new_index] = current;

            current = next;
        }
    }

    // 更新哈希表属性
    map->buckets = new_buckets;
    map->capacity = new_capacity;
    free(old_buckets);
}

// 插入/更新键值对
int hashmap_put(HashMap *map, const char *key, unsigned int value)
{
    if (!map || !key)
        return -1;

    // 检查扩容条件
    if ((double)map->size / map->capacity >= LOAD_FACTOR)
    {
        hashmap_resize(map);
    }

    unsigned long index = hash(key) % map->capacity;
    Node **current = &map->buckets[index];

    // 查找现有节点
    while (*current)
    {
        if (strcmp((*current)->key, key) == 0)
        {
            (*current)->value = value;
            return 0;
        }
        current = &(*current)->next;
    }

    // 创建新节点
    Node *new_node = node_create(key, value);
    if (!new_node)
        return -1;

    *current = new_node;
    map->size++;
    return 0;
}

// 查找键值对
unsigned int hashmap_get(HashMap *map, const char *key, unsigned int *found)
{
    if (!map || !key)
    {
        if (found)
            *found = 0;
        return 0;
    }

    unsigned long index = hash(key) % map->capacity;
    Node *current = map->buckets[index];

    while (current)
    {
        if (strcmp(current->key, key) == 0)
        {
            if (found)
                *found = 1;
            return current->value;
        }
        current = current->next;
    }

    if (found)
        *found = 0;
    return 0;
}

// 删除键值对
unsigned int hashmap_remove(HashMap *map, const char *key)
{
    if (!map || !key)
        return 0;

    unsigned long index = hash(key) % map->capacity;
    Node **current = &map->buckets[index];
    unsigned int removed_value = 0;

    while (*current)
    {
        if (strcmp((*current)->key, key) == 0)
        {
            Node *to_delete = *current;
            *current = to_delete->next;

            removed_value = to_delete->value;
            free(to_delete->key);
            free(to_delete);

            map->size--;
            return removed_value;
        }
        current = &(*current)->next;
    }

    return 0;
}

// 销毁哈希表
void hashmap_destroy(HashMap *map)
{
    if (!map)
        return;

    for (int i = 0; i < map->capacity; i++)
    {
        Node *current = map->buckets[i];
        while (current)
        {
            Node *next = current->next;
            free(current->key);
            free(current);
            current = next;
        }
    }
    free(map->buckets);
    free(map);
}

// 单元测试
void test_hashmap()
{
    HashMap *map = hashmap_create();

    // 测试插入和查找
    hashmap_put(map, "apple", 10);
    hashmap_put(map, "banana", 20);

    unsigned int found;
    unsigned int val = hashmap_get(map, "apple", &found);
    printf("Apple: %d (found=%d)\n", val, found); // 应输出10, found=1

    val = hashmap_get(map, "grape", &found);
    printf("Grape: %d (found=%d)\n", val, found); // 应输出0, found=0

    // 测试更新
    hashmap_put(map, "apple", 30);
    val = hashmap_get(map, "apple", &found);
    printf("Updated apple: %d\n", val); // 应输出30

    // 测试删除
    hashmap_remove(map, "banana");
    val = hashmap_get(map, "banana", &found);
    printf("After remove banana: found=%d\n", found); // found=0

    // 测试扩容
    for (unsigned int i = 0; i < 20; i++)
    {
        char key[10];
        sprintf(key, "key%d", i);
        hashmap_put(map, key, i);
    }
    printf("Map size after expansion: %d\n", map->size); // 应输出21

    // 测试遍历
    for (int i = 0; i < map->capacity; i++)
    {
        Node *current = map->buckets[i];
        while (current)
        {
            printf("Key: %s, Value: %d\n", current->key, current->value);
            current = current->next;
        }
    }

    hashmap_destroy(map);
}
unsigned int is_float(const char *str)
{
    unsigned int dot_count = 0; // 记录小数点的数量
    unsigned int len = strlen(str);

    // 检查字符串是否为空
    if (len == 0)
        return 0; // 空字符串不是浮点数

    // 检查第一个字符是否为小数点
    if (str[0] == '.')
        return 0; // 小数点不能单独存在

    // 检查小数点的数量
    for (int i = 0; i < len; i++)
    {
        if (str[i] == '.')
            dot_count++;
    }
    if (dot_count > 1)
        return 0; // 超过一个小数点不是浮点数

    // 检查其他字符是否为数字
    for (int i = 0; i < len; i++)
    {
        if (str[i] != '.' && (str[i] < '0' || str[i] > '9'))
            return 0; // 非数字字符不是浮点数
    }
    return 1; // 是浮点数
}
unsigned int is_int(const char *str)
{
    unsigned int len = strlen(str);
    for (int i = 0; i < len; i++)
    {
        if (str[i] < '0' || str[i] > '9')
            return 0; // 非数字字符不是整数
    }
    return 1; // 是整数
}
int loc_point(const char *str)
{
    unsigned int len = strlen(str);
    for (int i = 0; i < len; i++)
    {
        if (str[i] == '.')
            return i; // 找到小数点的位置
    }
    return -1; // 未找到小数点
}
int is_sepcial(const char *str)
{
    unsigned int len = strlen(str);
    for (int i = 0; i < len; i++)
    {
        if (str[i] == '^' || str[i] == '_')
            return 1; // 是特殊字符
    }
    return 0; // 不是特殊字符
}
int loc_sepcial(const char *str)
{
    unsigned int len = strlen(str);
    for (int i = 0; i < len; i++)
    {
        if (str[i] == '^' || str[i] == '_')
            return i; // 找到特殊字符的位置
    }
    return -1; // 未找到特殊字符
}
void show_message(const char *show, unsigned int *result, HashMap *map, unsigned int found)
{
    unsigned int length = strlen(show);
    if (length < 4)
    {
        for (int i = 0; i < strlen(show); i++)
        {
            char dest[2];
            strncpy(dest, show + i, 1);                                  // 复制小数点前的数字到dest中
            dest[1] = '\0';                                              // 确保字符串以null结尾
            *(result + 4 - length + i) = hashmap_get(map, dest, &found); // 小数点前的数字
        }
    }
    else
    {

        if (is_float(show)) // 浮点数
        {
            unsigned int point = loc_point(show);
            for (int i = 0; i < length; i++) // 浮点数length=5
            {
                if (i == point - 1)
                {
                    char dest[3];
                    strncpy(dest, show + i, 2);                     // 复制小数点前的数字到dest中
                    dest[2] = '\0';                                 // 确保字符串以null结尾
                    *(result + i) = hashmap_get(map, dest, &found); // 小数点前的数字
                    continue;
                }
                if (i == point)
                    continue;
                if (i > point)
                {
                    char dest[2];
                    strncpy(dest, show + i, 1);                         // 复制小数点后的数字到dest中
                    dest[1] = '\0';                                     // 确保字符串以null结尾
                    *(result + i - 1) = hashmap_get(map, dest, &found); // 小数点后的数字
                }
                else if (i < point)
                {
                    char dest[2];
                    strncpy(dest, show + i, 1);                     // 复制小数点前的数字到dest中
                    dest[1] = '\0';                                 // 确保字符串以null结尾
                    *(result + i) = hashmap_get(map, dest, &found); // 小数点前的数字
                }
            }
        }
        else if (is_sepcial(show)) // 含特殊字符
        {
            unsigned int sepcial = loc_sepcial(show);
            for (int i = 0; i < length; i++) // 含特殊字符length=5
            {
                if (i == sepcial)
                {
                    char dest[3];
                    strncpy(dest, show + i, 2);                     // 复制特殊字符后的字符到dest中
                    dest[2] = '\0';                                 // 确保字符串以null结尾
                    *(result + i) = hashmap_get(map, dest, &found); // 含特殊字符后的字符
                    continue;
                }
                if (i == sepcial + 1)
                    continue;
                if (i > sepcial + 1)
                {
                    char dest[2];
                    strncpy(dest, show + i, 1);                         // 复制特殊字符后的字符到dest中
                    dest[1] = '\0';                                     // 确保字符串以null结尾
                    *(result + i - 1) = hashmap_get(map, dest, &found); // 特殊字符后的字符
                }
                else if (i < sepcial + 1)
                {
                    char dest[2];
                    strncpy(dest, show + i, 1);                     // 复制特殊字符后的数字到dest中
                    dest[1] = '\0';                                 // 确保字符串以null结尾
                    *(result + i) = hashmap_get(map, dest, &found); // 特殊字符后的字符
                }
            }
        }
        else
        {
            for (int i = 0; i < 4; i++)
            {
                char dest[2];
                strncpy(dest, show + i, 1);                     // 复制小数点前的数字到dest中
                dest[1] = '\0';                                 // 确保字符串以null结尾
                *(result + i) = hashmap_get(map, dest, &found); // 小数点前的数字
            }
        }
    }
}
void my_test()
{
    HashMap *map = hashmap_create();
    hashmap_put(map, "0", 0x3f);
    hashmap_put(map, "1", 0x06);
    hashmap_put(map, "2", 0x5b);
    hashmap_put(map, "3", 0x4f);
    hashmap_put(map, "4", 0x66);
    hashmap_put(map, "5", 0x6d);
    hashmap_put(map, "6", 0x7d);
    hashmap_put(map, "7", 0x07);
    hashmap_put(map, "8", 0x7f);
    hashmap_put(map, "9", 0x6f);
    hashmap_put(map, "0.", 0xbf);
    hashmap_put(map, "1.", 0x86);
    hashmap_put(map, "2.", 0xdb);
    hashmap_put(map, "3.", 0xcf);
    hashmap_put(map, "4.", 0xe6);
    hashmap_put(map, "5.", 0xed);
    hashmap_put(map, "6.", 0xfd);
    hashmap_put(map, "7.", 0x87);
    hashmap_put(map, "8.", 0xff);
    hashmap_put(map, "9.", 0xef);
    hashmap_put(map, "A", 0x77);
    hashmap_put(map, "b", 0x7c);
    hashmap_put(map, "c", 0x39);
    hashmap_put(map, "d", 0x5e);
    hashmap_put(map, "E", 0x79);
    hashmap_put(map, "F", 0x71);
    hashmap_put(map, "L", 0x38);
    hashmap_put(map, "K", 0x78);
    hashmap_put(map, "M", 0x37);
    hashmap_put(map, "n", 0x54);
    hashmap_put(map, "G", 0x3d);
    hashmap_put(map, "J", 0x0e);
    hashmap_put(map, "^o", 0x63); // 上O
    hashmap_put(map, "_o", 0x5c); // 下O
    hashmap_put(map, "S", 0x6d);
    hashmap_put(map, "T", 0x31);
    hashmap_put(map, "p", 0x73);
    hashmap_put(map, "r", 0x50);
    hashmap_put(map, "y", 0x6e);
    hashmap_put(map, "i", 0x19);
    hashmap_put(map, "V", 0x1d);
    hashmap_put(map, "U", 0x3e);
    hashmap_put(map, "Z", 0x5b);
    hashmap_put(map, "x", 0x00);
    printf("map size: %d Byte\n", map->size * sizeof(Node));
    printf("Node size: %d Byte\n", sizeof(Node));

    const char *show = "xErr";
    unsigned int found = 0;
    unsigned int result[4] = {0}; // 存储结果的数组
    // printf("length of show: %d\n", strlen(show));
    // printf("%x\n", hashmap_get(map, "s", &found));
    // printf("%x\n", hashmap_get(map, "t", &found));
    // printf("%x\n", hashmap_get(map, "b", &found));
    // printf("%x\n", hashmap_get(map, "y", &found));

    show_message(show, result, map, found);

    for (int i = 0; i < 4; i++)
    {
        printf("0x%x,", result[i]);
    }
    hashmap_destroy(map);
}

int main()
{
    // test_hashmap();
    my_test();
    return 0;
}